#ifndef PAINTER_HPP
#define PAINTER_HPP

#include "models/Process.h"
#include "models/TimePoint.h"
#include "utils/Base64.h"
#include "utils/FifoPipe.h"
#include "utils/Types.h"
#include "wx/mstream.h"

#include <chrono>
#include <filesystem>
#include <stdexcept>
#include <string>
#include <thread>
#include <vector>

#include <wx/wx.h>

using models::Process;
using models::TimePoint;
using utils::FifoPipe;

class Painter {
public:
  Painter(const std::vector<Process> &processes,
          const std::vector<TimePoint> &time_points)
      : processes_(processes), time_points_(time_points),
        pipe_("/tmp/my_fifo") {
    if (std::filesystem::exists("output/finished.lock")) {
      std::filesystem::remove("output/finished.lock");
    }

    pipe_.writeMessage(models::TimePoint::to_json_any(time_points_).dump());
    system("scripts/.venv/bin/python3 scripts/main.py &");
    u32 timeout = 0;
    while (timeout < 10) {
      if (std::filesystem::exists("output/finished.lock")) {
        break;
      }
      std::this_thread::sleep_for(std::chrono::seconds(1));
      timeout++;
    }

    if (timeout >= 10) {
      throw std::runtime_error(
          "Timeout: output/finished.lock not found within 10 seconds");
    }
  }

  wxImage plot_all() {
    wxImage image;
    if (!image.LoadFile("output/plot_full.png", wxBITMAP_TYPE_PNG)) {
      throw std::runtime_error(
          "Failed to load image from output/plot_full.png");
    }
    return image;
  }

  wxImage plot_next_step() {
    wxImage image;
    std::string filename = "output/plot_step_" + std::to_string(step) + ".png";
    if (!image.LoadFile(filename, wxBITMAP_TYPE_PNG)) {
      throw std::runtime_error("Failed to load image from " + filename);
    }
    step++;
    return image;
  }

  void export_video(const std::string &output_filename) {
    if (!std::filesystem::exists("output/finished.lock")) {
      throw std::runtime_error("output/finished.lock not found");
    }
    if (std::filesystem::exists(output_filename)) {
      std::filesystem::remove(output_filename);
    }

    system(("ffmpeg -framerate 0.5 -pattern_type glob -i "
            "\"output/plot_step_*.png\" "
            "-c:v libx264 -r 30 -pix_fmt yuv420p " +
            output_filename)
               .c_str());
  }

private:
  std::vector<Process> processes_;
  std::vector<TimePoint> time_points_;
  FifoPipe pipe_;
  u32 step = 0;

  wxImage decodeBase64ToWxImage(const std::string &base64_str) {
    std::vector<unsigned char> image_data = base64_decode_to_vector(base64_str);
    wxMemoryInputStream stream(image_data.data(), image_data.size());
    wxImage image(stream, wxBITMAP_TYPE_PNG);
    return image;
  }
};
#endif